flamingo.me/flamingo-commerce/v3@v3.11.0/docs/1. Introduction/3. Coding Conventions.md (about)

     1  # Flamingo Commerce Coding Conventions
     2  
     3  ### Summary:
     4  * [Flamingo Coding Conventions](https://docs.flamingo.me/2.%20Flamingo%20Core/1.%20Flamingo%20Basics/8.%20Coding%20Conventions.html) are applied
     5  * We use Domain Driven Design and Ports and Adapters. Looking in the code should help understanding the e-commerce domain and should be semantic.
     6    
     7  ## Domain Driven Design
     8  ### Strategical
     9   
    10  * Each module represents an independent subdomain within the overall e-commerce area. 
    11  * Dependencies to modules should be treated just like third-party dependencies. Furthermore, module dependencies should only be introduced as less as possible, when they are useful and remain unidirectional. 
    12  
    13  ### Tactical
    14   
    15  * We stick to the [Flamingo Module structure](https://docs.flamingo.me/2.%20Flamingo%20Core/1.%20Flamingo%20Basics/3.%20Flamingo%20Module%20Structure.html) and use [Ports and Adapters](https://docs.flamingo.me/2.%20Flamingo%20Core/1.%20Flamingo%20Basics/4.%20Ports%20and%20Adapters.html)
    16  * Domain Layer should be technology free and should have potent model in the boundary of the module.
    17      * Normally should not need to know about Session and Framework specific stuff
    18  * Application Layer:
    19      * Should contain thin and useful "Services" or "Handlers" that provide a use case oriented access to the logic of the domain layer.
    20      * Is allowed to access Session and Framework modules
    21  
    22  ## Configuration
    23  Each module should document its supported configuration using cue.
    24  
    25  ## Runnable (aka FakeAdapters)
    26  Each module should be runnable by default:
    27  That means that the modules need to provide so called FakeAdapters for the required secondary ports. 
    28  The Adapters Binding should be activated by a Feature Flag (Configuration).
    29  
    30  ## Usage of Interfaces
    31  
    32  Using interfaces in Go allows us to describe behaviour without specifying an implementation.
    33  This proves very helpful when splitting definitions of a service, such as a domain service and the actual implementation, which can be specific to a certain technology/module.
    34  Additionally interfaces allow us to generate so-called "mocks", which can be used in unit tests, to assert and mock a certain interaction without actually implementing/using the original functionality.
    35  
    36  To prevent tight coupling across modules, each module should introduce their own interfaces which abstract the dependent module's functionnality. Those interfaces should be designed to include only what is needed by its hosting module and must not leak dependent types.
    37  
    38  In Flamingo Commerce we agreed in the following:
    39  
    40  ### Usage of interfaces For Secondary Ports
    41  Especially in the domain layer we use interfaces as secondary ports. 
    42  This is essentially the part where different Adapters can implement the technical details independent from the domain logic.
    43  
    44  The modules should contain at least a "FakeAdapter" for this interfaces in the infrastructure layer. 
    45  This is to demonstrate the use and to be "runnable" by default.
    46  
    47  ### For improved testability
    48  
    49  Defining interfaces other then for "secondary ports" makes sense to improve testability.
    50  This might be especially useful for application services (living in the application/ folder).
    51  
    52  There are two possible solutions to this problem:
    53  
    54  1. one is that the application provider provides an additional interface as well as a default implementation
    55  2. the other is that the consumer of a service specifies it's own interface.
    56  
    57  #### Approach 1. (define interface in the providing package)
    58  
    59  An module should provide an interface for its main application services if useful for testing:
    60  
    61  * The interface has the semantic name
    62  * The Implementation adds "Impl" to this name and is bound to the interface.
    63  
    64  Example:
    65  
    66  ```go
    67  // */application/service.go
    68  package application
    69  
    70  type (
    71      MyService interface {
    72        DoSomething()  
    73      }
    74  
    75      MyServiceImpl struct {
    76      
    77      }   
    78  )
    79  ```
    80  
    81  The module will need to Bind the `MyServiceImpl` for the interface `MyService` in its Dingo Module.
    82  
    83  Other places that need `MyService` will request the interface `MyService` - so that you can Unit Test this parts and provide a Mock instead of the Default Implementation.
    84  
    85  #### Approach 2. (define interface in the consuming package)
    86  Use this in cases where the provider does not provide an interface and you want to mock it.
    87  E.g. for external libs.
    88  
    89  
    90  ### General interface conventions
    91  
    92  * Dont blow up the interface with additional concepts - often its better to add a new interface with the extra "concern" or "concept". Smaller interfaces are better maintainable and it also helps reducing breaking changes.
    93  * Optional you can provide generated mocks (e.g. using a tool like mockery).